/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package g360.WebXpdlValidation;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;

/**
 *
 * @author andya
 */
public abstract class DomDocument 
{
    private Document domDocument = null;
    
    protected static Document parse(InputStream input, ErrorHandler errorHandler)
    {
        Document result = null;
        try 
        {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            if (errorHandler != null) 
            {
                db.setErrorHandler(errorHandler);
            }
            result = db.parse(input);
        } 
        catch (Exception ex) 
        {
            ex.printStackTrace();
        }
        return result;
    }
    
    
    protected DomDocument(Document domDoc)
    {
        this.domDocument = domDoc;
    }
    
    public Document getDomDocument()
    {
        return this.domDocument;
    }
    
    protected void setDomDocument(Document document) throws Exception
    {
        this.domDocument = document;
        initialize();
    }

    public ByteArrayInputStream getStream() throws IOException
    {
        DomSerializer serializer = new DomSerializer();
        serializer.setIndent(4);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        serializer.serialize(this.domDocument, outputStream);


        String s = outputStream.toString();
        byte[] byteArray = outputStream.toByteArray();
        ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
        return inputStream;
    }
    
    // Call whenever the document changes.
    protected abstract void initialize() throws Exception;
            
    public void reparse()
    {
        try 
        {
//            DomSerializer serializer = new DomSerializer();
//            serializer.setIndent(4);
//            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//            serializer.serialize(this.domDocument, outputStream);
//
//
//            String s = outputStream.toString();
//            byte[] byteArray = outputStream.toByteArray();
//            ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
            ByteArrayInputStream inputStream = this.getStream();
            Document reparsedDocument = DomDocument.parse(inputStream, null);
            this.setDomDocument(reparsedDocument);
        } 
        catch (Exception ex) 
        {
            ex.printStackTrace();
        }
        
    }
    
    public void load(InputStream inputStream)
    {
        
    }
    
    protected Node getFirstChild(Node node, String name)
    {
        Node result = null;
        NodeList list = node.getChildNodes();
        for (int i = 0; i < list.getLength(); i++)
        {
            Node child = list.item(i);
            String childLocalName = child.getLocalName();
            if ((childLocalName != null) && childLocalName.equalsIgnoreCase(name))
            {
                result = child;
            }
        }
        return result;
    }
    
    protected void insertAfter(Node parent, Node predecessor, Node newChild)
    {
        NodeList children = parent.getChildNodes();
        Node successor = null;
        for (int i = 0; i < children.getLength(); i++)
        {
            Node child = children.item(i);
            if (((i + 1) < children.getLength()) && (child == predecessor))
            {
                successor = children.item(i + 1);
                parent.insertBefore(newChild, successor);
            }
        }
        if (successor == null)
        {
            parent.appendChild(newChild);
        }
    }
    
    protected String getAttributeValue(Node node, String name)
    {
        String result = null;
        NamedNodeMap attributes = node.getAttributes();
        Node a = attributes.getNamedItem(name);
        if (a != null)
        {
            result = a.getNodeValue();
        }
        return result;
    }
    
    protected void setAttribute(Node node, String name, String value)
    {
        Attr attribute = this.domDocument.createAttribute(name);
        attribute.setValue(value);
        NamedNodeMap attributes = node.getAttributes();
        attributes.setNamedItem(attribute);
    }
    
    public void dump(String prefix)
    {
        this.dump(System.err, 50, prefix);
    }
    
    public void dump(java.io.PrintStream out, int levels, String prefix)
    {
        dump(out, this.domDocument, levels, prefix + "  ");
    }
    
    protected void dump(java.io.PrintStream out, Node node, int levels, String prefix)
    {
        if (levels > 0)
        {
            out.println(prefix + "Dumping node name=" + node.getNodeName() + " value=" + node.getNodeValue());
            out.print(prefix + "Attributes: ");
            NamedNodeMap attributes = node.getAttributes();
            if (attributes != null)
            {
                for (int i = 0; i < attributes.getLength(); i++)
                {
                    Node a = attributes.item(i);
                    out.print(a.getNodeName() + "==" + a.getNodeValue() + "; ");
                }
            }
            out.println();
            out.println(prefix + "Children:  ");
            NodeList children = node.getChildNodes();
            if (children != null)
            {
                for (int i = 0; i < children.getLength(); i++)
                {
                    dump(out, children.item(i), levels-1, prefix + "  ");
                }
            }
        }
    }
    
    protected void dumpNode(java.io.PrintStream out, Node node)
    {
        out.println();
        out.println("Dumping node name=" + node.getNodeName() + " value=" + node.getNodeValue());
        out.println("Attributes:");
        NamedNodeMap attributes = node.getAttributes();
        for (int i = 0; i < attributes.getLength(); i++)
        {
            Node a = attributes.item(i);
            out.println("name=" + a.getNodeName() + " value=" + a.getNodeValue());
        }
        out.println("Children:");
        NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); i++)
        {
            Node n = children.item(i);
            out.println("name=" + n.getNodeName() + " value=" + n.getNodeValue());
        }
    }

}
